package com.cardone.platform.configuration.service;

import java.io.File;
import java.util.List;
import java.util.Map;

import lombok.Getter;
import lombok.Setter;

import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.util.CollectionUtils;

import com.cardone.common.dto.PaginationDto;
import com.cardone.common.util.ExcelUtils;
import com.cardone.common.util.ExcelUtils.ExcelConfig;
import com.cardone.context.Attributes;
import com.cardone.context.ContextHolder;
import com.cardone.platform.common.util.EntityFileUtils;
import com.cardone.platform.configuration.dao.DictionaryDao;
import com.cardone.platform.configuration.dao.DictionaryTypeDao;
import com.cardone.platform.configuration.dto.DictionaryDto;
import com.cardone.platform.configuration.dto.DictionaryTypeDto;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

/**
 * 字典服务
 *
 * @author yaohaitao
 *
 */
@Getter
@Setter
public class DictionaryDefaultService implements DictionaryService {
	@Override
	public int deleteByIds(final DictionaryDto deleteDictionary) {
		return ContextHolder.getBean(DictionaryDao.class).deleteByIds(deleteDictionary);
	}

	@Override
	public <P> P findByCodeOrId(final Class<P> mappedClass, final DictionaryDto findDictionary) {
		return ContextHolder.getBean(DictionaryDao.class).findByCodeOrId(mappedClass, findDictionary);
	}

	@Override
	public <P> P findById(final Class<P> mappedClass, final DictionaryDto findDictionary) {
		return ContextHolder.getBean(DictionaryDao.class).findById(mappedClass, findDictionary);
	}

	@Override
	public <P> P findByTypeCodeAndCode(final Class<P> mappedClass, final String typeCode, final String code) {
		return ContextHolder.getBean(DictionaryDao.class).findByTypeCodeAndCode(mappedClass, typeCode, code);
	}

	@Override
	public <P> List<P> findListByLikeCode(final Class<P> mappedClass, final DictionaryDto findListDictionary) {
		return ContextHolder.getBean(DictionaryDao.class).findListByLikeCode(mappedClass, findListDictionary);
	}

	@Override
	public <P> List<P> findListByTypeCode(final Class<P> mappedClass, final String typeCode) {
		return ContextHolder.getBean(DictionaryDao.class).findListByTypeCode(mappedClass, typeCode);
	}

	@Override
	public <P> List<P> findListByTypeId(final Class<P> mappedClass, final String typeId) {
		return ContextHolder.getBean(DictionaryDao.class).findListByTypeId(mappedClass, typeId);
	}

	@Override
	public <V> Map<String, List<V>> findListMapByTypeCodeList(final Class<V> mappedClass, final List<String> typeCodeList) {
		if (CollectionUtils.isEmpty(typeCodeList)) {
			return null;
		}

		final Map<String, List<V>> dictionaryListMap = Maps.newLinkedHashMap();

		for (final String typeCode : typeCodeList) {
			dictionaryListMap.put(typeCode, ContextHolder.getBean(DictionaryDao.class).findListByTypeCode(mappedClass, typeCode));
		}

		return dictionaryListMap;
	}

	@Override
	public void importExcel(final String filename) throws Exception {
		final File file = new File(filename);

		EntityFileUtils.writeTo(file, filename);

		final Map<Integer, String> columns0 = Maps.newHashMap();

		columns0.put(0, Attributes.typeId.name());
		columns0.put(1, Attributes.typeCode.name());
		columns0.put(2, Attributes.typeName.name());
		columns0.put(3, "typeOrderNum");
		columns0.put(4, Attributes.id.name());
		columns0.put(5, Attributes.code.name());
		columns0.put(6, Attributes.name.name());
		columns0.put(7, Attributes.remark.name());
		columns0.put(8, DictionaryDto.Attributes.explain.name());
		columns0.put(9, Attributes.orderNum.name());

		final ExcelConfig excelConfig0 = ExcelConfig.newExcelConfig(columns0);

		excelConfig0.setFirstRowIndex(1);
		excelConfig0.setSheetIndexs(new int[] { 0 });

		ExcelUtils.readFile(file, Lists.newArrayList(excelConfig0));

		final List<DictionaryTypeDto> dictionaryTypeList = Lists.newArrayList();

		final Map<String, DictionaryTypeDto> dictionaryTypeMap = Maps.newHashMap();

		int dictonaryOrderNum = 0;

		int dictonaryTypeOrderNum = 0;

		for (final Map<String, Object> data : excelConfig0.getDataList()) {
			final String typeId = MapUtils.getString(data, Attributes.typeId.name());
			final String typeCode = MapUtils.getString(data, Attributes.typeCode.name());
			final String typeName = MapUtils.getString(data, Attributes.typeName.name());
			final Double typeOrderNum = MapUtils.getDouble(data, "typeOrderNum");
			final String id = MapUtils.getString(data, Attributes.id.name());
			final String code = MapUtils.getString(data, Attributes.code.name());
			final String name = MapUtils.getString(data, Attributes.name.name());
			final String remark = MapUtils.getString(data, Attributes.remark.name());
			final String explain = MapUtils.getString(data, DictionaryDto.Attributes.explain.name());
			final Double orderNum = MapUtils.getDouble(data, Attributes.orderNum.name());

			DictionaryTypeDto dictionaryType = dictionaryTypeMap.get(typeCode);

			if (dictionaryType == null) {
				dictionaryType = DictionaryTypeDto.newDictionaryType();

				dictionaryType.setId(typeId);

				dictionaryType.setCode(typeCode).setName(StringUtils.trim(typeName));

				if (typeOrderNum == null) {
					dictionaryType.setOrderNum(new Double(dictonaryTypeOrderNum++));
				} else {
					dictionaryType.setOrderNum(typeOrderNum);
				}

				dictionaryType.setDictionaryList(Lists.<DictionaryDto> newArrayList());

				dictionaryTypeMap.put(typeCode, dictionaryType);

				dictionaryTypeList.add(dictionaryType);

				dictonaryOrderNum = 0;
			}

			final DictionaryDto dictionary = DictionaryDto.newDictionary();

			dictionary.setId(id).setCode(code).setName(StringUtils.trim(name));

			dictionary.setRemark(remark).setExplain(explain);

			if (typeOrderNum == null) {
				dictionary.setOrderNum(new Double(dictonaryOrderNum++));
			} else {
				dictionary.setOrderNum(orderNum);
			}

			dictionaryType.getDictionaryList().add(dictionary);
		}

		this.init(dictionaryTypeList);
	}

	@Override
	public void init(final List<DictionaryTypeDto> initDictionaryTypeList) {
		if (CollectionUtils.isEmpty(initDictionaryTypeList)) {
			return;
		}

		for (final DictionaryTypeDto initDictionaryType : initDictionaryTypeList) {
			final DictionaryTypeDto oldDictionaryType = ContextHolder.getBean(DictionaryTypeDao.class).saveByIdOrCode(DictionaryTypeDto.class, initDictionaryType);

			if (!CollectionUtils.isEmpty(initDictionaryType.getDictionaryList())) {
				for (final DictionaryDto initDictionary : initDictionaryType.getDictionaryList()) {
					initDictionary.setTypeId(oldDictionaryType.getId());

					ContextHolder.getBean(DictionaryDao.class).saveByIdOrCode(DictionaryDto.class, initDictionary);
				}
			}

			if (CollectionUtils.isEmpty(initDictionaryType.getChilds())) {
				continue;
			}

			for (final DictionaryTypeDto childDictionaryTy : initDictionaryType.getChilds()) {
				childDictionaryTy.setParentId(oldDictionaryType.getId());
			}

			this.init(initDictionaryType.getChilds());
		}
	}

	@Override
	public int insertByCode(final DictionaryDto insertDictionary) {
		return ContextHolder.getBean(DictionaryDao.class).insertByCode(insertDictionary);
	}

	@Override
	public <P> PaginationDto<P> paginationByLikeCode(final Class<P> mappedClass, final DictionaryDto paginationDictionary) {
		return ContextHolder.getBean(DictionaryDao.class).paginationByLikeCode(mappedClass, paginationDictionary);
	}

	@Override
	public Integer readByCodeNqIdForCount(final DictionaryDto readDictionary) {
		return ContextHolder.getBean(DictionaryDao.class).readByCodeNqIdForCount(readDictionary);
	}

	@Override
	public String readIdByTypeCodeAndCode(final String typeCode, final String code) {
		final DictionaryDto DictionaryDto = ContextHolder.getBean(DictionaryService.class).findByTypeCodeAndCode(DictionaryDto.class, typeCode, code);

		if (DictionaryDto == null) {
			return null;
		}

		return DictionaryDto.getId();
	}

	@Override
	public String readIdByTypeCodeAndCode(final String defaultId, final String typeCode, final String code) {
		final String id = ContextHolder.getBean(DictionaryService.class).readIdByTypeCodeAndCode(typeCode, code);

		return StringUtils.defaultIfBlank(id, defaultId);
	}

	@Override
	public String readNameByTypeCodeAndCode(final String typeCode, final String code) {
		final DictionaryDto DictionaryDto = ContextHolder.getBean(DictionaryService.class).findByTypeCodeAndCode(DictionaryDto.class, typeCode, code);

		if (DictionaryDto == null) {
			return null;
		}

		return DictionaryDto.getName();
	}

	@Override
	public String readNameByTypeCodeAndCode(final String defaultName, final String typeCode, final String code) {
		final String name = ContextHolder.getBean(DictionaryService.class).readNameByTypeCodeAndCode(typeCode, code);

		return StringUtils.defaultIfBlank(name, defaultName);
	}

	@Override
	public String readValueByTypeCodeAndCode(final String typeCode, final String code) {
		final DictionaryDto DictionaryDto = ContextHolder.getBean(DictionaryService.class).findByTypeCodeAndCode(DictionaryDto.class, typeCode, code);

		if (DictionaryDto == null) {
			return null;
		}

		return DictionaryDto.getValue();
	}

	@Override
	public String readValueByTypeCodeAndCode(final String defaultValue, final String typeCode, final String code) {
		final String value = ContextHolder.getBean(DictionaryService.class).readValueByTypeCodeAndCode(typeCode, code);

		return StringUtils.defaultIfBlank(value, defaultValue);
	}

	@Override
	public <P> P saveByIdOrCode(final Class<P> mappedClass, final DictionaryDto saveDictionary) {
		return ContextHolder.getBean(DictionaryDao.class).saveByIdOrCode(mappedClass, saveDictionary);
	}

	@Override
	public int updateByCode(final DictionaryDto updateDictionary) {
		return ContextHolder.getBean(DictionaryDao.class).updateByCode(updateDictionary);
	}
}